package rds

import (
	"core/env"
	"core/utils"
	"time"

	"github.com/go-redis/redis"
)

type (
	//
	Client struct {
		redis.Client
	}

	// 基础排行榜信息
	BasicRankInfo struct {
		Member string `json:"member"` //
		Rank   int    `json:"rank"`   // 排名，从1开始
		Score  int64  `json:"score"`  //
	}
)

const (
	RankFactor = 10000000000
)

var (
	defaultClient     *Client   // 默认redis，存排行榜，配置信息等
	defaultClient2    *Client   // 默认redis2，存拼图圈图片
	cacheClientsCount int64     // 缓存redis数量
	cacheClients      []*Client // 缓存redis，可以删除的redis
)

func GetCacheClient(uid int64) *Client {
	return cacheClients[uid%cacheClientsCount]
}

func GetDefaultClient() *Client {
	return defaultClient
}

func GetPicClient() *Client {
	return defaultClient
}

func GetPicUploadClient(uid int64) *Client {
	return cacheClients[uid%cacheClientsCount]
}

func GetSyncClient() *Client {
	return defaultClient
}

func GetResizePicClient() *Client {
	return defaultClient2
}

// InitRedis 初始化redis
func InitRedis() (closeRds func(), err error) {
	defaultClient = &Client{Client: *redis.NewClient(&redis.Options{
		Addr:     env.Conf.DefaultRedis.Addr,
		Password: env.Conf.DefaultRedis.Password,
		DB:       env.Conf.DefaultRedis.DB,
	})}
	_, err = defaultClient.Ping().Result()
	if err != nil {
		return
	}

	defaultClient2 = &Client{Client: *redis.NewClient(&redis.Options{
		Addr:     env.Conf.DefaultRedis2.Addr,
		Password: env.Conf.DefaultRedis2.Password,
		DB:       env.Conf.DefaultRedis2.DB,
	})}
	_, err = defaultClient.Ping().Result()
	if err != nil {
		return
	}

	cacheClients = make([]*Client, 0)
	for _, conf := range env.Conf.CacheRedis {
		client := &Client{Client: *redis.NewClient(&redis.Options{
			Addr:     conf.Addr,
			Password: conf.Password,
			DB:       conf.DB,
		})}
		cacheClients = append(cacheClients, client)
	}
	cacheClientsCount = int64(len(cacheClients))

	closeRds = func() {
		defaultClient.Close()
		for _, client := range cacheClients {
			client.Close()
		}
	}
	return
}

// 获取基础排行榜信息, start:从0开始，limit，从0开始，例如：[0,99) 表示前一百名
func (c *Client) LoadRankList(key string, start, limit int64) (rankList []BasicRankInfo, err error) {
	list, err := c.ZRevRangeWithScores(key, start, limit-1).Result()
	if err != nil {
		return
	}
	rankList = make([]BasicRankInfo, len(list))
	for k, rank := range list {
		if member, ok := rank.Member.(string); ok {
			rankList[k] = BasicRankInfo{
				Member: member,
				Rank:   k + 1,
				Score:  int64(rank.Score) / RankFactor,
			}
		}
	}
	return
}

// 更新排行榜
// totalLenLimit 总长度限制 使用RankLimit类型是为了强制写常量
func (c *Client) UpdateRank(key string, member string, score int64, totalLenLimit int64) (err error) {
	utils.Info(score)
	utils.Info(float64(score*RankFactor + RankFactor - time.Now().Unix()))
	err = c.ZAdd(key, redis.Z{
		Member: member,
		Score:  float64(score*RankFactor + RankFactor - time.Now().Unix()),
	}).Err()
	if err != nil {
		return
	}

	count := c.ZCard(key).Val()
	if count > totalLenLimit*2 {
		err = c.ZRemRangeByRank(key, 0, -totalLenLimit).Err()
		if err != nil {
			return
		}
	}
	return
}

// 更新排行榜
// totalLenLimit 总长度限制 使用RankLimit类型是为了强制写常量
// 使用默认的分数
func (c *Client) UpdateRankWithScore(key string, member string, score float64, totalLenLimit int64) (err error) {
	err = c.ZAdd(key, redis.Z{
		Member: member,
		Score:  score,
	}).Err()
	if err != nil {
		return
	}

	count := c.ZCard(key).Val()
	if count > totalLenLimit*2 {
		err = c.ZRemRangeByRank(key, 0, -totalLenLimit).Err()
		if err != nil {
			return
		}
	}
	return
}

// 获取我的排名, rank:从1开始
func (c *Client) LoadMyRank(key, member string) (rank int64, err error) {
	rank, err = c.ZRevRank(key, member).Result()
	if err != nil {
		rank = -1
	}
	rank++
	return
}
